package com.walter.common.globalResponse;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.walter.common.basic.ResultVO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Objects;

/**
 *  全局响应数据预处理器，使用RestControllerAdvice和ResponseBodyAdvice
 *  拦截Controller方法默认返回参数，统一处理响应体
 * @author Walter
 * @date 2025/1/20 上午11:34
 **/
@RestControllerAdvice
@Slf4j
public class RestResponseHandler implements ResponseBodyAdvice<Object> {
    // 属性名称，用于记录是否标注了ResponseResultVO注解
    public static final String RESPONSE_RESULTVO_ATTR= "RESPONSE_RESULTVO_ATTR";
    @Resource
    private ObjectMapper objectMapper;

    /**
     * 判断是否需要执行beforeBodyWrite方法，true为执行；false为不执行
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        // 判断请求是否有注解标记。需要在拦截器中放入
         ResponseResultVO responseResultVO = (ResponseResultVO) request.getAttribute(RESPONSE_RESULTVO_ATTR);
         return Objects.nonNull(responseResultVO);
    }

    /**
     * 对返回值包装处理
     * @param body
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        // 已经返回的是Result类型对象了，直接返回，比如全局异常处理之后直接返回了
         if (body instanceof ResultVO) {
             return body;
         }
         //如果Controller直接返回String时，需要转换为Json，因为强化的是RestController
         if (body instanceof  String) {
              try {
                  return objectMapper.writeValueAsString(ResultVO.success(body));
              } catch (JsonProcessingException e) {
                  log.error("writeValueAsString error",e);
              }
         }
         return ResultVO.success(body);
    }
}
